/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package ant.antsys;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.HashSet;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.*;

/**
 * Define test suite in the sustem test
 * @author johnson ma
 */
public class TestSuite extends TestTask {

	private static final String LOG_PREFIX = "_output.log";
	private String name;
	private boolean failOnError = false;
	private String toDir = ".";
	private boolean htmlReport = false;

	public void init() {
		super.init();
		listeners.add(new LogTestListener());
		listeners.add(new TestMonitor());
	}

	// The method executing the task
	public void execute() throws BuildException {
		if (name == null) {
		    throw new BuildException("The name attribute must be present.",
				    getLocation());
		}

                if (!checkCondition()) {
                    return;
                }

		//check testcases for duplicate names
		HashSet testCaseNames = new HashSet();
		for (Task t : tasks) {
			if (t instanceof UnknownElement) {
				((UnknownElement) t).maybeConfigure();
				t = ((UnknownElement) t).getTask();
				if (t == null) {
					continue;
				}
			}
			if (t instanceof TestCase) {
				TestCase tc = (TestCase) t;
				String name = tc.getName();
				if (testCaseNames.contains(name)) {
					throw new BuildException("duplicate test case name " + name);
				}
				tc.setFailOnError(failOnError);
				testCaseNames.add(name);
			}
		}

		//tee system out and system error to log file  
		FileOutputStream fos = null;
		try {
			File dir = new File(toDir);
			if (!dir.exists()) {
				dir.mkdirs();
			}
			File logFile = new File(toDir, name + LOG_PREFIX);
			try {
				fos = new FileOutputStream(logFile);
			} catch (FileNotFoundException fe) {
				fe.printStackTrace();
			}
			System
					.setOut(new PrintStream(
							new TeeOutputStream(System.out, fos)));
			System
					.setErr(new PrintStream(
							new TeeOutputStream(System.err, fos)));
			;
			notifySuiteStart(this);
			for (Task t : tasks) {
				t.perform();
			}
			notifySuiteFinish(this);
		} finally {
			System.setOut(System.out);
			System.setErr(System.err);
			if (fos != null) {
				try {
					fos.close();
				} catch (Exception e) {
				}
				fos = null;
			}
		}
	}

	// The setter for the "name" attribute
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setFailOnError(boolean failOnError) {
		this.failOnError = failOnError;
	}

	public void setToDir(String toDir) {
		this.toDir = toDir;
	}

	public String getToDir() {
		return toDir;
	}

	public void setHtmlReport(boolean htmlReport) {
		this.htmlReport = htmlReport;
	}

	public boolean getHtmlReport() {
		return htmlReport;
	}

	private class TeeOutputStream extends OutputStream {
		private OutputStream[] outs;

		private TeeOutputStream(OutputStream... outs) {
			this.outs = outs;
		}

		public void write(int b) throws IOException {
			for (int i = 0; i < outs.length; i++) {
				outs[i].write(b);
			}
		}

	}

}


